home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Python 1.1 / Demo / turing / turing.py < prev   
Encoding:
Text File  |  1994-04-28  |  4.5 KB  |  181 lines  |  [TEXT/R*ch]

  1. ################################################################################
  2. # Turing machine simulation in Python (to prove that python is Turing
  3. # complete :-))
  4. #
  5. # This program reads in a state transition file (the program) and from
  6. # that and the initial tape that you specify, emulates a Turing machine
  7. # executing that program.  State 0 is the halting state.
  8. #
  9. # Each state transition has the following syntax:
  10. #
  11. #    <state, char> --> <new-state, operation>
  12. #
  13. # Where operation is:
  14. #
  15. #    L    move the tape head left 1 place.
  16. #    R    move the tape head right 1 place.
  17. #    char    write the character "char" to the tape.
  18. #
  19. # (I'm aware that some Turing machine models allow you to write to the
  20. # tape and move in one transition.  These programs require the new TuringDX
  21. # processor :-))
  22. #
  23. # This program also times the result (We used this program as a comparative
  24. # benchmark to compare Python's performance to other dynamic languages.
  25. # For the curious, Turing began its life as a C++ program.)  Since most
  26. # simulations finish in less than a second, you can have the program repeat a
  27. # computation a specified number of times.  (and some systems (i.e. DOS)
  28. # have low resolution timers)
  29. ################################################################################
  30.  
  31.  
  32. from string import *
  33. from sys    import exit
  34.  
  35.  
  36. #---------------------------------------------------------------------------#
  37. #                main
  38. #---------------------------------------------------------------------------#
  39.  
  40. def main():
  41.     from sys import argv
  42.  
  43.     if len(argv) == 3:
  44.     count = 1
  45.  
  46.     elif len(argv) != 4:
  47.     print 'usage:', argv[0], 'file inputstring [count]'
  48.     exit(0)
  49.  
  50.     else:
  51.     count = atoi(argv[3])
  52.  
  53.     turing(argv[1], argv[2], count)
  54.  
  55.  
  56.  
  57. #---------------------------------------------------------------------------#
  58. #    load, execute, & time a turing machine
  59. #---------------------------------------------------------------------------#
  60.  
  61. def turing(filename, initial_tape, count):
  62.     from time import time
  63.  
  64.     if filename[-3:] != '.tm':
  65.     filename = filename + '.tm'
  66.  
  67.     program = load(open(filename, 'r'))
  68.  
  69.     t1 = time()
  70.     for i in xrange(count):
  71.     pos, tape = execute(program, initial_tape)
  72.     t2 = time()
  73.  
  74.     print tape
  75.     print '%s^' % (' '*pos)
  76.  
  77.     if (t2 - t1) >= 0.1:
  78.     print '%.1f seconds.' % (t2 - t1)
  79.  
  80.  
  81.  
  82. #---------------------------------------------------------------------------#
  83. #            run the machine
  84. #---------------------------------------------------------------------------#
  85.  
  86. def execute(program, tape):
  87.     state = 1
  88.     pos   = 0
  89.  
  90.     while state != 0:
  91.     if pos < len(tape):            # read from the tape
  92.         char = tape[pos]
  93.     else:
  94.         char = ' '
  95.  
  96.     try:
  97.         iw = program[(state, char)]        # get instruction word;
  98.  
  99.     except KeyError:
  100.         print 'No valid transition exists for state', (state, char)
  101.         exit(1)
  102.  
  103.     if iw[1] == 'L':        # iw[1] is operation; iw[0] is new state
  104.         if pos > 0:
  105.         pos = pos - 1
  106.         else:
  107.         tape = ' ' + tape
  108.  
  109.     elif iw[1] == 'R':
  110.         pos = pos + 1
  111.  
  112.     else:
  113.         new_char = iw[1][1]        # write the new character to tape
  114.         if pos < len(tape):
  115.         tape = tape[:pos] + new_char + tape[pos+1:]
  116.         else:
  117.         tape = tape + ' '*(pos - len(tape)) + new_char
  118.  
  119.     state = iw[0]
  120.  
  121.     return pos, tape
  122.  
  123.  
  124.  
  125. #---------------------------------------------------------------------------#
  126. #    load the turing machine into memory; return it as a mapping
  127. #---------------------------------------------------------------------------#
  128.  
  129. def load(input):
  130.     import regex
  131.     from regex_syntax import *
  132.  
  133.     program = {}
  134.  
  135.     _  = regex.set_syntax(RE_SYNTAX_AWK)
  136.     re = regex.compile("<([0-9]+),'(.)'>--><([0-9]+),(L|R|'.')>$")
  137.  
  138.     lines = input.readlines()
  139.     for lineno, line in filter(lambda pair: len(pair[1]) > 0,
  140.                 map(lambda x,y: (x+1, strip(y)),
  141.                     xrange(len(lines)), lines)):
  142.     if re.match(line) == -1:
  143.         raise SyntaxError, `lineno` + ': Bad syntax for state transition'
  144.  
  145.     state, char, new_state, operation = re.group(1, 2, 3, 4)
  146.     program[(atoi(state), char)] = (atoi(new_state), operation)
  147.  
  148.     return program
  149.  
  150.  
  151.  
  152. #---------------------------------------------------------------------------#
  153. #    strip comments and white space from state transition lines
  154. #---------------------------------------------------------------------------#
  155.  
  156. def strip(str):
  157.     result  = ''
  158.     i = 0
  159.  
  160.     while i < len(str):
  161.     if str[i] in whitespace:
  162.         i = i + 1
  163.  
  164.     elif str[i] == ';':
  165.         break
  166.  
  167.     elif str[i] == '\'':
  168.         result = result + str[i:i+3]
  169.         i = i + 3
  170.  
  171.     else:
  172.         result = result + str[i]
  173.         i = i + 1
  174.  
  175.     return result
  176.  
  177.  
  178.  
  179. if __name__ == '__main__':
  180.     main()
  181.